package com.itmake.sample.server.monitor.util;

import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.system.*;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.itmake.sample.server.monitor.model.vo.server.*;
import com.itmake.sample.toolbox.capacity.ConvertUtil;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.software.os.OSFileStore;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 服务器信息工具类
 *
 * @author Amjacks
 * @since 2023/08/10
 */
public class ServerInfoUtil {

    private ServerInfoUtil () {}

    /**
     * cpu
     * @return cpu 信息
     */
    public static CpuVo getCpu () {
        CpuInfo cpuInfo = OshiUtil.getCpuInfo();
        CpuVo cpuVo = new CpuVo();
        cpuVo.setCpuNum(cpuInfo.getCpuNum());
        cpuVo.setTotal(cpuInfo.getToTal());
        cpuVo.setSys(cpuInfo.getSys());
        cpuVo.setUsed(cpuInfo.getUsed());
        cpuVo.setWait(cpuInfo.getWait());
        cpuVo.setFree(cpuInfo.getFree());
        return cpuVo;
    }

    /**
     * jvm
     * @return jvm 信息
     */
    public static JvmVo getJvm() {
        JavaRuntimeInfo javaRuntimeInfo = SystemUtil.getJavaRuntimeInfo();
        RuntimeInfo runtimeInfo = SystemUtil.getRuntimeInfo();
        RuntimeMXBean runtimeMXBean = SystemUtil.getRuntimeMXBean();
        JvmVo jvmVo = new JvmVo();
        jvmVo.setTotal(convertToMb(runtimeInfo.getTotalMemory()));
        jvmVo.setMax(convertToMb(runtimeInfo.getMaxMemory()));
        jvmVo.setFree(convertToMb(runtimeInfo.getFreeMemory()));
        jvmVo.setVersion(javaRuntimeInfo.getVersion());
        jvmVo.setHome(javaRuntimeInfo.getHomeDir());
        Date serverTime = DateUtil.date(ManagementFactory.getRuntimeMXBean().getStartTime());
        // JDK 启动时间
        jvmVo.setStartTime(DateUtil.format(serverTime, DatePattern.NORM_DATETIME_PATTERN));
        // JDK 运行时间
        jvmVo.setRunTime(DateUtil.formatBetween(DateUtil.date(), serverTime, BetweenFormatter.Level.SECOND));
        jvmVo.setUsage(calPercent(runtimeInfo.getTotalMemory() - runtimeInfo.getFreeMemory(), runtimeInfo.getTotalMemory()));
        jvmVo.setUsed(convertToMb(runtimeInfo.getTotalMemory() - runtimeInfo.getFreeMemory()));
        jvmVo.setName(runtimeMXBean.getVmName());
        return jvmVo;
    }

    /**
     * 内存
     * @return 内存信息
     */
    public static MemVo getMemory() {
        GlobalMemory memory = OshiUtil.getMemory();
        MemVo memVo = new MemVo();
        memVo.setTotal(convertToGb(memory.getTotal()));
        memVo.setUsed(convertToGb(memory.getTotal() - memory.getAvailable()));
        memVo.setFree(convertToGb(memory.getAvailable()));
        memVo.setUsage(calPercent(memory.getTotal() - memory.getAvailable(), memory.getTotal()));
        return memVo;
    }

    /**
     * 系统
     * @return 系统信息
     */
    public static SysVo getSysVo() {
        OsInfo osInfo = SystemUtil.getOsInfo();
        HostInfo hostInfo = SystemUtil.getHostInfo();
        UserInfo userInfo = SystemUtil.getUserInfo();
        SysVo sysVo = new SysVo();
        sysVo.setComputerName(hostInfo.getName());
        sysVo.setComputerIp(hostInfo.getAddress());
        sysVo.setUserDir(userInfo.getCurrentDir());
        sysVo.setOsName(osInfo.getName());
        sysVo.setOsArch(osInfo.getArch());
        return sysVo;
    }

    /**
     * 文件系统
     * @return 文件系统信息
     */
    public static List<SysFileVo> getSysFiles() {
        List<SysFileVo> sysFileVoList = new ArrayList<>();
        SystemInfo si = new SystemInfo();
        List<OSFileStore> fileStores = si.getOperatingSystem().getFileSystem().getFileStores();
        for (OSFileStore fileStore : fileStores) {
            long free = fileStore.getUsableSpace();
            long total = fileStore.getTotalSpace();
            long used = total - free;
            SysFileVo sysFileVo = new SysFileVo();
            sysFileVo.setDirName(fileStore.getMount());
            sysFileVo.setSysTypeName(fileStore.getType());
            sysFileVo.setTypeName(fileStore.getName());
            sysFileVo.setTotal(ConvertUtil.convertFileSize(total));
            sysFileVo.setFree(ConvertUtil.convertFileSize(free));
            sysFileVo.setUsed(ConvertUtil.convertFileSize(total - free));
            sysFileVo.setUsage(calPercent(used, total));
            sysFileVoList.add(sysFileVo);
        }
        return sysFileVoList;
    }

    /**
     * 转换到 MB
     */
    private static double convertToMb(double total) {
        return NumberUtil.div(total, (1024 * 1024), 2);
    }

    /**
     * 转换到 GB
     */
    private static double convertToGb(double total) {
        return NumberUtil.div(total, (1024 * 1024 * 1024), 2);
    }

    /**
     * 计算百分比
     */
    private static double calPercent(double number, double total) {
        return NumberUtil.mul(NumberUtil.div(number, total, 4), 100);
    }
}
